package com.aw.baselib.util

import com.aw.baselib.util.AwDataUtil.getLongValue
import com.aw.baselib.util.AwDataUtil.isEmpty
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Arrays
import java.util.Calendar
import java.util.Collections
import java.util.Date
import java.util.Locale
import java.util.TimeZone

/**
 * @author : hzw
 */
/**
 * @author : hzw
 */
object AwDateUtil {
    /**
     * 1s==1000ms
     */
    private const val TIME_MILLISECONDS = 1000

    /**
     * 时间中的分、秒最大值均为60
     */
    private const val TIME_NUMBERS = 60

    /**
     * 时间中的小时最大值
     */
    private const val TIME_HOURSES = 24

    /**
     * 格式化日期的标准字符串
     */
    const val FORMAT_YMD_HMS = "yyyy-MM-dd HH:mm:ss"
    const val FORMAT_YMD_HM = "yyyy-MM-dd HH:mm"
    const val FORMAT_YMD = "yyyy-MM-dd"
    const val FORMAT_YMD2 = "yyyyMMdd"
    private val MONTH_EN =
        arrayOf("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
    val timeZone: TimeZone
        /**
         * 获取时区信息
         */
        get() = TimeZone.getDefault()

    /**
     * 将日期字符串转换为Date对象, 默认样式YMD_HMS
     *
     * @param date 日期字符串，必须为"yyyy-MM-dd HH:mm:ss"
     * @return 日期字符串的Date对象表达形式
     */
    fun parseDefaultFormatDate(date: String?): Date? {
        return parseDate(date, FORMAT_YMD_HMS)
    }

    /**
     * 将日期字符串转换为Date对象
     *
     * @param date   日期字符串，必须为"yyyy-MM-dd HH:mm:ss"
     * @param format 格式化字符串
     * @return 日期字符串的Date对象表达形式
     */
    fun parseDate(date: String?, format: String?): Date? {
        var dt: Date? = null
        val dateFormat = SimpleDateFormat(format)
        try {
            dt = dateFormat.parse(date)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return dt
    }

    /**
     * 将Date对象转换为指定格式的字符串, 默认返回格式 YMD_HMS
     *
     * @param date Date对象
     * @return Date对象的字符串表达形式"yyyy-MM-dd HH:mm:ss"
     */
    fun formatDate(date: Date?): String {
        return if (date == null) {
            ""
        } else formatDate(
            date,
            FORMAT_YMD_HMS
        )
    }

    /**
     * 将Date对象转换为指定格式的字符串
     *
     * @param date   Date对象
     * @param format 格式化字符串
     * @return Date对象的字符串表达形式
     */
    @JvmStatic
    fun formatDate(date: Date?, format: String?): String {
        val dateFormat = SimpleDateFormat(format)
        return dateFormat.format(date)
    }

    /**
     * 将Date对象转换为指定格式的字符串
     * @param date
     * @param simpleDateFormat 格式化样式, 单独提供, 方便适配外国日期样式
     * @return
     */
    fun formatDate(date: Date?, simpleDateFormat: SimpleDateFormat): String {
        return simpleDateFormat.format(date)
    }

    /**
     * 格式化unix时间戳日期, 默认返回格式 YMD_HMS
     *
     * @param unixTime unix时间戳
     * @return 日期字符串"yyyy-MM-dd HH:mm:ss"
     */
    fun formatUnixTime(unixTime: String?): String {
        return if (isEmpty(unixTime)) {
            ""
        } else formatUnixTime(
            getLongValue(
                unixTime!!
            ), FORMAT_YMD_HMS
        )
    }

    /**
     * 格式化unix时间戳日期
     *
     * @param unixTime unix时间戳
     * @return 日期字符串"yyyy-MM-dd HH:mm:ss"
     */
    fun formatUnixTime(unixTime: String?, format: String?): String {
        return if (isEmpty(unixTime)) {
            ""
        } else formatUnixTime(
            getLongValue(
                unixTime!!
            ), format
        )
    }
    /**
     * 格式化unix时间戳日期
     *
     * @param unixTime unix时间戳
     * @param format   格式化字符串
     * @return 日期字符串
     */
    /**
     * 格式化unix时间戳日期, 默认返回格式 YMD_HMS
     *
     * @param unixTime unix时间戳 1970-01-01T00:00:00Z.
     * @return 日期字符串"yyyy-MM-dd HH:mm:ss"
     */
    @JvmOverloads
    fun formatUnixTime(unixTime: Long, format: String? = FORMAT_YMD_HMS): String {
        val dateFormat = SimpleDateFormat(format)
        return dateFormat.format(unixTime)
    }
    /**
     * 将GMT日期格式化为系统默认时区的日期字符串表达形式
     *
     * @param gmtUnixTime GTM时间戳
     * @param format      格式化字符串
     * @return 日期字符串"yyyy-MM-dd HH:mm:ss"
     */
    /**
     * 将GMT日期格式化为系统默认时区的日期字符串表达形式
     *
     * @param gmtUnixTime GTM时间戳
     * @return 日期字符串"yyyy-MM-dd HH:mm:ss"
     */
    @JvmOverloads
    fun formatGMTUnixTime(gmtUnixTime: Long, format: String? = FORMAT_YMD_HMS): String {
        val dateFormat = SimpleDateFormat(format)
        return dateFormat.format(gmtUnixTime + TimeZone.getDefault().rawOffset)
    }

    /**
     * 获取时间戳的Date表示形式
     *
     * @param unixTime unix时间戳
     * @return Date对象
     */
    fun getUnixDate(unixTime: Long): Date {
        return Date(unixTime)
    }

    /**
     * 获取GMT时间戳的Date表示形式（转换为Date表示形式后，为系统默认时区下的时间）
     *
     * @param gmtUnixTime GMT Unix时间戳
     * @return Date对象
     */
    fun getGMTDate(gmtUnixTime: Long): Date {
        return Date(gmtUnixTime + TimeZone.getDefault().rawOffset)
    }

    /**
     * 将系统默认时区的Unix时间戳转换为GMT Unix时间戳
     *
     * @param unixTime unix时间戳
     * @return GMT Unix时间戳
     */
    fun getGMTUnixTime(unixTime: Long): Long {
        return unixTime - TimeZone.getDefault().rawOffset
    }

    /**
     * 将GMT Unix时间戳转换为系统默认时区的Unix时间戳
     *
     * @param gmtUnixTime GMT Unix时间戳
     * @return 系统默认时区的Unix时间戳
     */
    fun getCurrentTimeZoneUnixTime(gmtUnixTime: Long): Long {
        return gmtUnixTime + TimeZone.getDefault().rawOffset
    }

    val gMTUnixTimeByCalendar: Long
        /**
         * 获取当前时间的GMT Unix时间戳
         *
         * @return 当前的GMT Unix时间戳
         */
        get() {
            val calendar = Calendar.getInstance()
            // 获取当前时区下日期时间对应的时间戳
            val unixTime = calendar.timeInMillis
            // 获取标准格林尼治时间下日期时间对应的时间戳
            return unixTime - TimeZone.getDefault().rawOffset
        }
    val unixTimeByCalendar: Long
        /**
         * 获取当前时间的Unix时间戳
         *
         * @return 当前的Unix时间戳
         */
        get() {
            val calendar = Calendar.getInstance()
            // 获取当前时区下日期时间对应的时间戳
            return calendar.timeInMillis
        }

    /**
     * 获取更改时区后的时间
     *
     * @param date    时间
     * @param oldZone 旧时区
     * @param newZone 新时区
     * @return 时间
     */
    fun getChangeZoneTime(date: Date?, oldZone: TimeZone, newZone: TimeZone): Date? {
        var dateTmp: Date? = null
        if (date != null) {
            val timeOffset = oldZone.rawOffset - newZone.rawOffset
            dateTmp = Date(date.time - timeOffset)
        }
        return dateTmp
    }

    /**
     * 将总秒数转换为时分秒表达形式
     *
     * @param seconds 任意秒数
     * @return %s小时%s分%s秒
     */
    fun formatTime(seconds: Long): String {
        val hh = seconds / TIME_NUMBERS / TIME_NUMBERS
        val mm =
            if (seconds - hh * TIME_NUMBERS * TIME_NUMBERS > 0) (seconds - hh * TIME_NUMBERS * TIME_NUMBERS) / TIME_NUMBERS else 0
        val ss = if (seconds < TIME_NUMBERS) seconds else seconds % TIME_NUMBERS
        return ((if (hh == 0L) "" else (if (hh < 10) "0$hh" else hh).toString() + "小时")
                + (if (mm == 0L) "" else (if (mm < 10) "0$mm" else mm).toString() + "分")
                + if (ss == 0L) "" else (if (ss < 10) "0$ss" else ss).toString() + "秒")
    }

    /**
     * 获取当前时间距离指定日期时差的大致表达形式
     *
     * @param date 日期
     * @return 时差的大致表达形式
     */
    fun getDiffTimeDesc(date: Long): String {
        var strTime = "很久很久以前"
        val time = Math.abs(Date().time - date)
        // 一分钟以内
        if (time < TIME_NUMBERS * TIME_MILLISECONDS) {
            strTime = "刚刚"
        } else {
            val min = (time / TIME_MILLISECONDS / TIME_NUMBERS).toInt()
            if (min < TIME_NUMBERS) {
                strTime = if (min < 15) {
                    "一刻钟前"
                } else if (min < 30) {
                    "半小时前"
                } else {
                    "1小时前"
                }
            } else {
                val hh = min / TIME_NUMBERS
                if (hh < TIME_HOURSES) {
                    strTime = hh.toString() + "小时前"
                } else {
                    val days = hh / TIME_HOURSES
                    if (days <= 6) {
                        strTime = days.toString() + "天前"
                    } else {
                        val weeks = days / 7
                        if (weeks < 3) {
                            strTime = weeks.toString() + "周前"
                        }
                    }
                }
            }
        }
        return strTime
    }

    val todayZeroTime: Long
        /**
         * 获取当天0点时间戳
         * @return
         */
        get() {
            val calendar = Calendar.getInstance()
            calendar[Calendar.HOUR_OF_DAY] = 0
            calendar[Calendar.MINUTE] = 0
            calendar[Calendar.SECOND] = 0
            return calendar.timeInMillis
        }

    /**
     * 判断传入时间字符串  是否是当天
     * @param dateStr
     * @return
     */
    fun isToday(dateStr: String?): Boolean {
        var dateStr = dateStr ?: return false
        val sdf = SimpleDateFormat("MMMM dd,yyyy")
        dateStr = sdf.format(Date(java.lang.Long.valueOf(dateStr)))
        val dateStrCurrent = sdf.format(Date())
        return if (dateStr != null && dateStrCurrent != null && dateStr == dateStrCurrent) true else false
    }

    /**
     * 功能：判断日期是否和当前date对象在同一天。
     * 参见：http://www.cnblogs.com/myzhijie/p/3330970.html
     *
     * @param date 比较的日期
     * @return boolean 如果在返回true，否则返回false。
     */
    fun isSameDay(date: Date?): Boolean {
        requireNotNull(date) { "date is null" }
        val nowCalendar = Calendar.getInstance()
        val newCalendar = Calendar.getInstance()
        newCalendar.time = date
        return nowCalendar[Calendar.ERA] == newCalendar[Calendar.ERA] && nowCalendar[Calendar.YEAR] == newCalendar[Calendar.YEAR] && nowCalendar[Calendar.DAY_OF_YEAR] == newCalendar[Calendar.DAY_OF_YEAR]
    }

    /**
     * 获取当前时间前12个月集合
     * @return
     */
    fun getPreMonthList(format: String?): List<String?> {
        val list: MutableList<String?> = ArrayList()
        for (i in 0..11) {
            list.add(getFormatSpecDate(System.currentTimeMillis(), Calendar.MONTH, -i, format))
        }
        Collections.reverse(list)
        return list
    }

    /**
     * 时间转换, 秒转换为 时分秒显示
     * @param secondsTime
     * @return
     */
    fun convertTimeToHms(secondsTime: String): String {
        if (isEmpty(secondsTime)) {
            return ""
        }
        val seconds = secondsTime.toInt()
        AwLog.d("===>seconds: $seconds")
        var timeStr: String? = null
        var hour = 0
        var minute = 0
        var second = 0
        minute = seconds / 60
        AwLog.d("===>minute: $minute")
        if (minute < 60) {
            second = seconds % 60
            AwLog.d("===>second: $second")
            timeStr = if (second == 0) {
                if (minute == 0) {
                    "0"
                } else {
                    minute.toString() + "m"
                }
            } else {
                if (minute == 0) {
                    if (second == 0) {
                        "0"
                    } else {
                        second.toString() + "s"
                    }
                } else {
                    if (second == 0) {
                        minute.toString() + "m"
                    } else {
                        minute.toString() + "m" + second + "s"
                    }
                }
            }
        } else {
            hour = minute / 60
            minute = minute % 60
            second = seconds - hour * 3600 - minute * 60
            val sb = StringBuffer()
            if (hour != 0) {
                sb.append(hour.toString() + "h")
            }
            if (minute != 0) {
                sb.append(minute.toString() + "m")
            }
            if (second != 0) {
                sb.append(second.toString() + "s")
            }
            timeStr = if (hour == 0 && minute == 0 && second == 0) {
                "0"
            } else {
                sb.toString()
            }
        }
        return timeStr
    }

    /**
     * 时间转换  秒转分
     */
    fun convertSecondToMin(s: Int): String {
        var timeStr: String? = null
        var hour = 0
        var minute = 0
        var second = 0
        minute = s / 60
        if (minute < 60) {
            second = s % 60
            timeStr = formatAddPre_0(minute) + ":" + formatAddPre_0(second)
        } else {
            hour = minute / 60
            if (hour > 99) return ""
            minute = minute % 60
            second = s - hour * 3600 - minute * 60
            timeStr =
                formatAddPre_0(hour) + ":" + formatAddPre_0(minute) + ":" + formatAddPre_0(second)
        }
        return timeStr
    }

    /**
     * 时间表示调整, 小于10, 前面添加0
     * @param i
     * @return
     */
    private fun formatAddPre_0(i: Int): String {
        var retStr: String? = null
        retStr = if (i >= 0 && i < 10) "0$i" else "" + i
        return retStr
    }

    /**
     * 判断时间是否通过
     * ===> 结束时间大于等于开始时间
     * @param startTime
     * @param endTime
     * @param format 如yyyy-MM-dd HH:mm
     * @return
     */
    fun isTimePass(startTime: String?, endTime: String?, format: String?): Boolean {
        val dateFormat = SimpleDateFormat(format)
        try {
            val date1 = dateFormat.parse(startTime) //开始时间
            val date2 = dateFormat.parse(endTime) //结束时间
            // 1 结束时间小于开始时间 2 开始时间与结束时间相同 3 结束时间大于开始时间
            if (date2.time < date1.time) {
                return false
            } else if (date2.time == date1.time) {
                return true
            } else if (date2.time > date1.time) {
                //正常情况下的逻辑操作.
                return true
            }
        } catch (e: ParseException) {
            e.printStackTrace()
        }
        return false
    }

    /**
     * 格式化指定日期
     * @param originTime
     * @param calendarField
     * @param param
     * @param format
     * @return
     */
    fun getFormatSpecDate(
        originTime: Long,
        calendarField: Int,
        param: Int,
        format: String?
    ): String {
        return formatDate(getSpecDate(originTime, calendarField, param), format)
    }

    /**
     * 获取指定时间戳的 param 差时间戳
     * @param originTime
     * @param calendarField 如以下传参
     * 年 Calendar.YEAR
     * 月 Calendar.MONTH (结果需+1),
     * 日 Calendar.DAY_OF_MONTH
     * 时 Calendar.HOUR_OF_DAY
     * 分 Calendar.MINUTE
     * 秒 Calendar.SECOND
     * @param param 时间差, 如前一天 -1, 后3天 3等
     * @return
     */
    @JvmStatic
    fun getSpecDate(originTime: Long, calendarField: Int, param: Int): Date {
        val cal = Calendar.getInstance()
        cal.timeInMillis = originTime
        cal.add(calendarField, param)
        return cal.time
    }

    /**
     * 根据传入time时间戳 获取指定time的时间段, 如何年, 月, 日, 时, 分, 秒...
     * @param time
     * @param calendarField 如以下传参
     * 年 Calendar.YEAR
     * 月 Calendar.MONTH (结果需+1),
     * 日 Calendar.DAY_OF_MONTH
     * 时 Calendar.HOUR_OF_DAY
     * 分 Calendar.MINUTE
     * 秒 Calendar.SECOND
     * @return
     */
    fun getSpecTimeType(time: Long, calendarField: Int): Int {
        val cal = Calendar.getInstance()
        cal.timeInMillis = time
        return if (calendarField == Calendar.MONTH) {
            cal[calendarField] + 1
        } else {
            cal[calendarField]
        }
    }

    /**
     * 外国时间样式
     * 02-23-2022 , 11:01:43 AM
     * February-23-2022 , 11:01:43 AM
     * @param time
     * @param formatStyle 如 MM-dd-yyyy hh:mm:ss aa, MMMM-dd-yyyy , hh:mm:ss aa等
     * @return
     */
    fun getForeignCountryTime(time: String, formatStyle: String?): String {
        if (isEmpty(time)) {
            return ""
        }
        val date = Date(time.toLong())
        //        SimpleDateFormat format = new SimpleDateFormat("MMMM-dd-yyyy , hh:mm:ss aa", Locale.US);
        val sdf = SimpleDateFormat(formatStyle, Locale.ENGLISH)
        return formatDate(date, sdf)
    }

    /**
     * 判断是否在当前日期之后
     * @param paramTime
     * @return
     */
    fun isAfterCurrentTime(paramTime: String?, format: String?): Boolean {
        val dateFormat = SimpleDateFormat(format) //年-月-日 时-分
        try {
            val paramDate = dateFormat.parse(paramTime) //参数时间
            val currentDate = Date() //当前时间
            if (paramDate.time < currentDate.time) {
                //参数时间在当前时间之前
                return false
            } else if (paramDate.time == currentDate.time) {
                return true
            } else if (paramDate.time > currentDate.time) {
                //参数时间在当前时间之后
                return true
            }
        } catch (e: ParseException) {
            e.printStackTrace()
        }
        return false
    }

    /**
     * 获取过去第几天的日期
     *
     * @param past
     * @return
     */
    fun getPastDate(past: Int): String {
        val calendar = Calendar.getInstance()
        calendar[Calendar.DAY_OF_YEAR] = calendar[Calendar.DAY_OF_YEAR] - past
        val date = calendar.time
        val format =
            SimpleDateFormat(FORMAT_YMD_HMS)
        return format.format(date)
    }

    /**
     * 获取未来 第 past 天的日期
     *
     * @param past
     * @return
     */
    fun getFetureDate(past: Int): String {
        val calendar = Calendar.getInstance()
        calendar[Calendar.DAY_OF_YEAR] = calendar[Calendar.DAY_OF_YEAR] + past
        val today = calendar.time
        val format =
            SimpleDateFormat(FORMAT_YMD_HMS)
        return format.format(today)
    }

    /**
     * 获取某年某月第一天0点
     *
     * @param year
     * @param month
     * @return
     */
    fun getFirstDayOfMonthStartTime(year: Int, month: Int): Long {
        val calendar = Calendar.getInstance()
        calendar[year, month - 1, 1, 0] = 0 // 设置为某月的第一天0点
        calendar[Calendar.MILLISECOND] = 0 // 清除毫秒数
        return calendar.timeInMillis // 获取该时间的时间戳
    }

    /**
     * 获取某年某月最后一天12点
     *
     * @param year
     * @param month
     * @return
     */
    fun getLastDayOfMonthEndTime(year: Int, month: Int): Long {
        val calendar = Calendar.getInstance()
        calendar[year, month - 1, calendar.getActualMaximum(Calendar.DAY_OF_MONTH), 12] =
            0 // 设置为某月的最后一天12点
        calendar[Calendar.MILLISECOND] = 0 // 清除毫秒数
        return calendar.timeInMillis // 获取该时间的时间戳
    }

    /**
     * 计算两个日期之间相差的时间戳数
     */
    private fun calculateDifference(startDate: Date, endDate: Date): LongArray {
        var differentMilliSeconds = endDate.time - startDate.time
        val secondsInMilli: Long = 1000 //1s==1000ms
        val minutesInMilli = secondsInMilli * 60
        val hoursInMilli = minutesInMilli * 60
        val daysInMilli = hoursInMilli * 24
        val elapsedDays = differentMilliSeconds / daysInMilli
        differentMilliSeconds = differentMilliSeconds % daysInMilli
        val elapsedHours = differentMilliSeconds / hoursInMilli
        differentMilliSeconds = differentMilliSeconds % hoursInMilli
        val elapsedMinutes = differentMilliSeconds / minutesInMilli
        differentMilliSeconds = differentMilliSeconds % minutesInMilli
        val elapsedSeconds = differentMilliSeconds / secondsInMilli
        return longArrayOf(elapsedDays, elapsedHours, elapsedMinutes, elapsedSeconds)
    }

    /**
     * 计算每月的天数
     */
    fun calculateDaysInMonth(month: Int): Int {
        return calculateDaysInMonth(0, month)
    }

    /**
     * 根据年份及月份计算每月的天数
     */
    fun calculateDaysInMonth(year: Int, month: Int): Int {
        // 添加大小月月份并将其转换为list,方便之后的判断
        val bigMonths = arrayOf("1", "3", "5", "7", "8", "10", "12")
        val littleMonths = arrayOf("4", "6", "9", "11")
        val bigList = Arrays.asList(*bigMonths)
        val littleList = Arrays.asList(*littleMonths)
        // 判断大小月及是否闰年,用来确定"日"的数据
        return if (bigList.contains(month.toString())) {
            31
        } else if (littleList.contains(month.toString())) {
            30
        } else {
            if (year <= 0) {
                return 29
            }
            // 是否闰年
            if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
                29
            } else {
                28
            }
        }
    }

    /**
     * 月日时分秒，0-9前补0
     */
    fun fillZero(number: Int): String {
        return if (number < 10) "0$number" else "" + number
    }

    /**
     * 截取掉前缀0以便转换为整数
     *
     * @see .fillZero
     */
    fun trimZero(text: String): Int {
        var text = text
        return try {
            if (text.startsWith("0")) {
                text = text.substring(1)
            }
            text.toInt()
        } catch (e: NumberFormatException) {
            e.printStackTrace()
            0
        }
    }
}